Test Failed
Push — dependabot/npm_and_yarn/handle... ( 471819 )
by
unknown
11:45 queued 06:13
created

blockutils.js ➔ ... ➔ ???   A

Complexity

Conditions 3
Paths 7

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.0175

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
c 1
b 0
f 0
nc 7
nop 3
dl 0
loc 16
ccs 7
cts 8
cp 0.875
crap 3.0175
rs 9.6
1
/*jslint node: true, nomen: true, regexp: true, plusplus: true */
2
(function () {
3
4
    "use strict";
5
6
    const   request     = require("request"),
7
            RateLimiter = require("limiter").RateLimiter;
8
9
    class BlockUtils {
10
11
        constructor(apiUrl, magicToken, signalApiUrl, perSecondRateLimit)
12
        {
13
            this.API_URL = apiUrl;
14
            this.MAGIC_TOKEN = magicToken;
15
            this.SIGNAL_API_URL = signalApiUrl;
16
            this.limiter = new RateLimiter(perSecondRateLimit, 'second');
17
        }
18
19
        /**
20
         * Allow to use callback-style methods with promises
21
         * @param {Array}       args            Original function arguments
22
         * @param {Number}      optionsOffset   Expected offset of the options object in the arguments
23
         * @callback
24
         * @private
25
         */
26
        _handlePromises(args, optionsOffset, callback) {
27
            let fCallback = args[args.length - 1];
28
            const checkArgsAndGo = (options = {}) => {
29
                if (args[optionsOffset] !== fCallback) {
30
                    options = args[optionsOffset];
31
                }
32
                callback(options, fCallback);
33
            };
34
            if (typeof fCallback === "function") {
35
                return checkArgsAndGo();
36
            }
37
            return new Promise((resolve, reject) => {
38
                fCallback = (err, res) => {
39
                    if (err) { return reject(err); }
40
                    return resolve(res);
41
                };
42
                checkArgsAndGo();
43
            });
44
        }
45
46
        /**
47
         * Make and return the call to the API
48
         * @param endpoint
49
         * @param callback
50
         * @private
51
         */
52
        call() {
53
            return this._handlePromises(arguments, 1, ({
54
                useSignalAPI = false,
55
                method = "GET",
56
                body = null
57
            } = {}, callback) => {
58
                this.limiter.removeTokens(1, () => {
59
                    request({
60
                        method: method,
61
                        url: ((useSignalAPI) ? this.SIGNAL_API_URL : this.API_URL) + arguments[0],
62
                        headers: {"magic": this.MAGIC_TOKEN},
63
                        body: body
64
                    }, (err, result, body) => {
65
                        try {
66
                            const tBody = JSON.parse(body);
67
68
                            return callback(null, tBody);
69
                        } catch (e) {
70
                            // Exceptions for plain text responses
71
                            if (body === "success") {
72
                                return callback(null, body);
73
                            } else if (body === "fail") {
74
                                return callback(new Error("FAIL"));
75
                            }
76
77
                            return callback(e, body);
78
                        }
79
                    });
80
                });
81
            });
82
        }
83
84
        /**
85
         * Parse and format a token pair
86
         * @param tokenStr String containing the token (ie. "XRP/BTC", "AEON", "USD-LTC", ...)
87
         * @returns {*} Structure with base & token values (default base is BTC)
88
         * @private
89
         */
90
        parseToken(tokenStr) {
91
            // Token is already parsed
92
            if (typeof tokenStr === "object") { return tokenStr; }
93
94
            // Check token format
95
            if (tokenStr.indexOf("/") > -1) { // Classic representation
96
                const [token, base] = tokenStr.split("/");
97
                return {base, token};
98
            } else if(tokenStr.indexOf("-") > -1) { // Inversed one
99
                const [base, token] = tokenStr.split("-");
100
                return {base, token};
101
            } else { // Raw token without attached base
102
                return {base: "BTC", token: tokenStr};
103
            }
104
        }
105
106
        /**
107
         * Create a new fake device to use with Blockfolio & return the Blockfolio instance
108
         * @callback
109
         * @private
110
         */
111
        generateClientToken() {
112
            return parseInt(Math.random().toString().substring(2)).toString(12);
113
        }
114
    }
115
116
    module.exports = BlockUtils;
117
118
})();